import styled from 'styled-components'
import React, { useCallback, useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Item from './Item'
import Cell, { ProgressProps } from '../../component/Cell'
import Icon from '../../component/Icon'
import Empty from '../../component/Empty'
import IconAnticipate from '../../asserts/icon_anticipate.png'
import { Task, TaskResponse, TaskTypes } from '../../service/interface'
import { taskDone, taskPrize, tasks } from '../../service'
import Message from '../../component/Message'
import WebApp from '@twa-dev/sdk'
import gtag from '../../google/analytics'
import { GtagEvent } from '../../google/analytics/Event'
import { useTonAddress, useTonConnectUI } from '@tonconnect/ui-react'
import RouterProtocol, { Actions, Protocol } from '../../utils/protocol'
import { formatStrToPoint } from '../../utils/string'
import Loading from '../../component/Loading'

enum Status {
    undo = 0,
    done,
    unclaim,
}

type TaskProps = Task & { _protocol?: Protocol }

// type CellProps = { key: string, des: string, status: Status, title?: string };

const KEYS = {
    COMMUNITY: 'community',
    INVITE: 'invite',
    OTHER: 'other'
}

const Container = styled.div`
    display: flex;
    flex-direction: column;
    padding: 0 1rem 1.625rem;
    box-sizing: border-box;
`

const Menu = styled.div`
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1rem; 
`

const List = styled.div`
    margin-top: 1rem;
    width: 100%;
    flex: 1;
`

const CellBox = styled(Cell)`
    margin-bottom: 1rem;
    position: relative;
    .progress {
        height: 1rem;
    }
`

const Text = styled.div<{ $hasIcon: number }>`
    margin-left: ${({ $hasIcon }) => $hasIcon ? '6px' : 0};
`

const RightItem = styled.div<{ $background: string }>`
    width: 3.125rem;
    height: 1.5rem;
    background: ${({ $background }) => $background};
    border-radius: .5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: .625rem;
    font-weight: bold;
`

const Bottom = styled.div`
    width: 100%;
    font-size: .625rem;
    color: #8D98A6;
    text-align: end;
    position: absolute;
    right: 1rem;
    bottom: .1875rem;
`

const EmptyBox = styled(Empty)`
    height: 12.5rem;
    background-color: ${(prop) => prop.theme.background.box};
    padding-bottom: 0;
    flex-direction: column-reverse;
    font-size: .875rem;
    font-weight: bold;
    color: ${(prop) => prop.theme.text.normal};
    border-radius: .625rem;
    gap: .625rem;
`

interface Props {
    className?: string;
    onGetReward?: () => void;
}

const Content: React.FC<Props> = ({ className, onGetReward }) => {
    const { t } = useTranslation()
    const [tonConnectUI] = useTonConnectUI();
    const userFriendlyAddress = useTonAddress();
    const [current, setCurrent] = useState(KEYS.COMMUNITY)
    const [loading, setLoading] = useState(false)
    const [data, setData] = useState<{ [key: string]: Task[] }>({});

    const menus: { key: string, title: string, type: TaskTypes }[] = useMemo(() => {
        return [
            { key: KEYS.COMMUNITY, title: t('task.community'), type: TaskTypes.Community },
            { key: KEYS.INVITE, title: t('task.invite'), type: TaskTypes.Invite },
            { key: KEYS.OTHER, title: t('task.other'), type: TaskTypes.Other }
        ]
    }, [t])

    const fetchData = useCallback(async () => {
        setLoading(true)
        const res = await tasks();
        setLoading(false)
        if (!res.success) {
            Message.error(res.message)
            return;
        }

        const data = res.data?.reduce((draft: { [key in TaskTypes]?: TaskResponse }, value) => {
            draft[value.taskTypes] = value;
            return draft;
        }, {}) || {};

        const obj = menus.reduce((draft: { [key: string]: Array<Task> }, value) => {
            const type = value.type;
            const item = data[type];
            if (item) {
                const list = item.taskList.map(element => ({
                    ...element,
                    status: Number(element.takeSate)
                }))
                draft[value.key] = list;
            }
            return draft;
        }, {})
        setData(obj)
    }, [menus])

    const checkNew = useCallback((type: string) => {
        const list = data[type] || [];
        return list.findIndex(e => e.status === Status.unclaim) !== -1
    }, [data])

    useEffect(() => {
        fetchData();
    }, [fetchData])

    const list = useMemo(() => data[current] || [], [data, current])
    const progress = useCallback((item: Task) => {
        if (item.taskType === TaskTypes.Invite) {
            const data: ProgressProps = {
                percent: (item.progressValue / item.progressMax) * 100,
                showInfo: false,
                strokeColor: '#01BFBF',
                trailColor: '#32465E',
                size: ['100%', 4],
                rootClassName: 'progress',
            }
            return data;
        }
        return undefined
    }, [])

    const bottom = useCallback((item: TaskProps) => {
        if (!item._protocol) {
            item._protocol = RouterProtocol.parse(item.url) || { protocol: '', action: Actions.None }
        }

        if (item._protocol.action !== Actions.ConnectWallet || !userFriendlyAddress) {
            return
        }
        return <Bottom>{formatStrToPoint(userFriendlyAddress, 8, 8)}</Bottom>
    }, [userFriendlyAddress])


    const handleClick = (key: string) => {
        setCurrent(key)
    }

    const onRightClick = async (event: React.MouseEvent<HTMLDivElement, MouseEvent>, item: Task) => {
        event.stopPropagation();
        const status = item.status;
        if (status === Status.done) {
            return
        }

        if (status === Status.unclaim) {
            const res = await taskPrize({ taskId: String(item.taskId) })
            if (res.success) {
                Message.success({ element: t('modal.good'), position: 'center' })
                fetchData();
                onGetReward?.();
                return
            }
            Message.error(res.message)
        }
    }

    const finishTask = useCallback(async (item: Task) => {
        if (item.status === Status.undo) {
            const res = await taskDone({ taskId: String(item.taskId) })
            if (res.success) {
                fetchData();
            }
            return true;
        }
        return false
    }, [fetchData])

    const onCellClick = async (item: TaskProps) => {
        const status = item.status;
        const info = item._protocol || RouterProtocol.parse(item.url)
        if (info?.action === Actions.WebView) {
            WebApp.openLink(item.url)
            const map: { [key: number]: string } = {
                14: 'twitter',
                15: 'telegram'
            }
            gtag.event(GtagEvent.Task, {
                status,
                type: item.taskName,
                name: map[item.taskId] || 'unknown'
            })

            await finishTask(item)
            return
        }

        if (info?.action === Actions.ConnectWallet) {
            try {
                if (!tonConnectUI.connected) {
                    const unsubscribe = tonConnectUI.onModalStateChange((state) => {
                        if (state.status === 'opened') {
                            return
                        }
                        if (state.closeReason === 'wallet-selected' && tonConnectUI.connected) {
                            finishTask(item)
                        }
                        unsubscribe()
                    })

                    tonConnectUI.openModal()
                    gtag.event(GtagEvent.Task, {
                        status,
                        type: item.taskName,
                        name: 'connectWallet'
                    })
                    return
                }
                await finishTask(item)
            } catch (error) {
                // temp
            }
        }
    }

    return <Container className={className}>
        <Menu>
            {menus.map(item => <Item
                hasNew={checkNew(item.key)}
                active={current === item.key}
                key={item.key}
                title={item.title}
                onClick={() => handleClick(item.key)}
            />)}
        </Menu>
        <List>
            {list.length ? list.map((item, idx) => <CellBox
                onClick={() => onCellClick(item)}
                key={idx}
                title={item.taskName}
                subTitle={
                    <>
                        <Icon
                            name='icon_coin'
                            width='0.75rem'
                        />
                        <Text $hasIcon={1}>{item.rewardAmt}</Text>
                    </>
                }
                icon={
                    <Icon
                        src={item.icon}
                        width='2rem'
                        height='2rem'
                        raduis="50%"
                    />
                }
                arrow={item.status === Status.undo}
                rightItem={item.status !== Status.undo ?
                    <RightItem
                        $background={item.status === Status.unclaim ? '#01BFBF' : '#3FCF77'}
                        onClick={(event) => onRightClick(event, item)}
                    >
                        {item.status === Status.unclaim ? t('task.get') : <Icon
                            name='task_success'
                            width='1.25rem'
                        />}
                    </RightItem> : (item.taskType === TaskTypes.Invite ? <RightItem
                        $background='#32465E'
                        onClick={(event) => onRightClick(event, item)}
                    >{t('task.get')}</RightItem> : undefined)}
                progress={progress(item)}
                bottom={bottom(item)}
            />) : <EmptyBox
                icon={IconAnticipate}
                width='3.875rem'
                title={t('common.comingSoon')}
            />}
        </List>
        <Loading show={loading} />
    </Container>
}

export default Content